/*
 * Copyright (c) 2009-2022 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*============================ INCLUDES ======================================*/

#include "arm_2d.h"

#ifdef __RTE_ACCELERATION_ARM_2D_SCENE3__

#define __USER_SCENE3_IMPLEMENT__
#include "arm_2d_scene_3.h"

#include "arm_2d_scenes.h"

#include "arm_2d_helper.h"
#include "arm_extra_controls.h"

#include <stdlib.h>
#include <string.h>

#include "main.h"

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wunknown-warning-option"
#   pragma clang diagnostic ignored "-Wreserved-identifier"
#   pragma clang diagnostic ignored "-Wsign-conversion"
#   pragma clang diagnostic ignored "-Wpadded"
#   pragma clang diagnostic ignored "-Wcast-qual"
#   pragma clang diagnostic ignored "-Wcast-align"
#   pragma clang diagnostic ignored "-Wmissing-field-initializers"
#   pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#   pragma clang diagnostic ignored "-Wmissing-prototypes"
#   pragma clang diagnostic ignored "-Wunused-variable"
#   pragma clang diagnostic ignored "-Wgnu-statement-expression"
#   pragma clang diagnostic ignored "-Wdeclaration-after-statement"
#   pragma clang diagnostic ignored "-Wunused-function"
#   pragma clang diagnostic ignored "-Wmissing-declarations"  
#elif __IS_COMPILER_ARM_COMPILER_5__
#elif __IS_COMPILER_IAR__
#   pragma diag_suppress=Pa089,Pe188,Pe177,Pe174
#elif __IS_COMPILER_GCC__
#   pragma GCC diagnostic push
#   pragma GCC diagnostic ignored "-Wformat="
#   pragma GCC diagnostic ignored "-Wpedantic"
#endif

/*============================ MACROS ========================================*/

#if __GLCD_CFG_COLOUR_DEPTH__ == 8

#   define c_tileCMSISLogo          c_tileCMSISLogoGRAY8

#elif __GLCD_CFG_COLOUR_DEPTH__ == 16

#   define c_tileCMSISLogo          c_tileCMSISLogoRGB565

#elif __GLCD_CFG_COLOUR_DEPTH__ == 32

#   define c_tileCMSISLogo          c_tileCMSISLogoCCCA8888
#else
#   error Unsupported colour depth!
#endif

/*============================ MACROFIED FUNCTIONS ===========================*/
#undef this
#define this (*ptThis)

/*============================ TYPES =========================================*/
/*============================ GLOBAL VARIABLES ==============================*/

extern const arm_2d_tile_t c_tileCMSISLogo;
extern const arm_2d_tile_t c_tileCMSISLogoMask;
extern const arm_2d_tile_t c_tileCMSISLogoA2Mask;
extern const arm_2d_tile_t c_tileCMSISLogoA4Mask;
/*============================ PROTOTYPES ====================================*/
/*============================ LOCAL VARIABLES ===============================*/
/*============================ IMPLEMENTATION ================================*/


static void __on_scene3_depose(arm_2d_scene_t *ptScene)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)ptScene;
    ARM_2D_UNUSED(ptThis);
    
    ptScene->ptPlayer = NULL;
    
    /* reset timestamp */
    this.lTimestamp = 0;
    PAGE_SWITCHING = false;
    
    BUTTON_1 = NONE_PRESS;
    BUTTON_2 = NONE_PRESS;
    BUTTON_3 = NONE_PRESS;
    if (!this.bUserAllocated) {
        free(ptScene);
    }
}

/*----------------------------------------------------------------------------*
 * Scene 3                                                                    *
 *----------------------------------------------------------------------------*/

static void __on_scene3_background_start(arm_2d_scene_t *ptScene)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static void __on_scene3_background_complete(arm_2d_scene_t *ptScene)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}


static void __on_scene3_frame_start(arm_2d_scene_t *ptScene)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)ptScene;
    ARM_2D_UNUSED(ptThis);

}

static uint8_t item = 0;
static bool item_state[8] = {0};
static void __on_scene3_frame_complete(arm_2d_scene_t *ptScene)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)ptScene;
    ARM_2D_UNUSED(ptThis);
    
    if(BUTTON_2==LONG_PRESS_START && PAGE_SWITCHING==false){
        PAGE_SWITCHING = true;
        arm_2d_scene0_init(&DISP0_ADAPTER);
        arm_2d_scene_player_switch_to_next_scene(ptScene->ptPlayer);
    }
    
    if(BUTTON_1 == PRESS_DOWN){
        item = item<7?item+1:0;
        BUTTON_1 = NONE_PRESS;
    }
    
    if(BUTTON_2 == SINGLE_CLICK){
        bool state = true;
        LINKS_GET_PAUSE(item, &state)
        LINKS_SET_PAUSE(item, !state)
        item_state[item] = !state;
        BUTTON_2 = NONE_PRESS;
    }
    
    if(BUTTON_3 == PRESS_DOWN){
        item = item>0?item-1:7;
        BUTTON_3 = NONE_PRESS;
    }
}

static
IMPL_PFB_ON_DRAW(__pfb_draw_scene3_background_handler)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)pTarget;
    ARM_2D_UNUSED(ptTile);
    ARM_2D_UNUSED(bIsNewFrame);
    /*-----------------------draw back ground begin-----------------------*/



    /*-----------------------draw back ground end  -----------------------*/
    arm_2d_op_wait_async(NULL);

    return arm_fsm_rt_cpl;
}


extern const arm_2d_tile_t c_tileWhiteDotMask;
extern const arm_2d_tile_t c_tileWhiteDotRGB565;


static arm_2d_location_t local[] = {
    {  5, 5},
    { 50, 5},
    { 95, 5},
    {140, 5},
    {  5,60},
    { 50,60},
    { 95,60},
    {140,60},
};

static
IMPL_PFB_ON_DRAW(__pfb_draw_scene3_handler)
{
    user_scene_3_t *ptThis = (user_scene_3_t *)pTarget;
    ARM_2D_UNUSED(ptTile);
    ARM_2D_UNUSED(bIsNewFrame);
    
//    arm_2d_canvas(ptTile, __top_container) {
    /*-----------------------draw the foreground begin-----------------------*/    
    arm_2d_fill_colour(ptTile, NULL, GLCD_COLOR_BLACK);
        
    arm_2dp_fill_colour_with_opacity(   
                                    NULL,
                                    ptTile, 
                                    &(arm_2d_region_t) {
                                        .tSize = {
                                            .iHeight = 25,
                                            .iWidth = 25,
                                        },
                                        .tLocation = {
                                            .iX = local[item].iX-5,
                                            .iY = local[item].iY-5,
                                        },
                                    }, 
                                    (__arm_2d_color_t){__RGB(0xFF, 0xB9, 0x00)},
                                    200);
    
    do{
        arm_2d_region_t tDotRegion  = c_tileWhiteDotRGB565.tRegion;
        for(uint8_t i=0; i<8; i++)
        {
            if(item_state[i]){
                tDotRegion.tLocation.iX = local[i].iX;
                tDotRegion.tLocation.iY = local[i].iY;
                arm_2d_fill_colour_with_mask_and_opacity(   
                                                        ptTile,
                                                        &tDotRegion,
                                                        &c_tileWhiteDotMask,
                                                        (__arm_2d_color_t){GLCD_COLOR_RED},
                                                        255);
            }
            else{
                tDotRegion.tLocation.iX = local[i].iX;
                tDotRegion.tLocation.iY = local[i].iY;
                arm_2d_fill_colour_with_mask_and_opacity(   
                                                        ptTile,
                                                        &tDotRegion,
                                                        &c_tileWhiteDotMask,
                                                        (__arm_2d_color_t){GLCD_COLOR_WHITE},
                                                        255);
            }
         }
    }while(0);



    /*-----------------------draw the foreground end  -----------------------*/
//    }
    arm_2d_op_wait_async(NULL);

    return arm_fsm_rt_cpl;
}

ARM_NONNULL(1)
user_scene_3_t *__arm_2d_scene3_init(   arm_2d_scene_player_t *ptDispAdapter, 
                                        user_scene_3_t *ptThis)
{
    bool bUserAllocated = false;
    assert(NULL != ptDispAdapter);

    /*! define dirty regions */
    IMPL_ARM_2D_REGION_LIST(s_tDirtyRegions, static)

        /* a dirty region to be specified at runtime*/
        ADD_REGION_TO_LIST(s_tDirtyRegions,
            0  /* initialize at runtime later */
        ),
        
        /* add the last region:
         * it is the top left corner for text display 
         */
        ADD_LAST_REGION_TO_LIST(s_tDirtyRegions,
            .tLocation = {
                .iX = 0,
                .iY = 0,
            },
            .tSize = {
                .iWidth = __GLCD_CFG_SCEEN_WIDTH__,
                .iHeight = 8,
            },
        ),

    END_IMPL_ARM_2D_REGION_LIST()
    
    /* get the screen region */
    arm_2d_region_t tScreen
        = arm_2d_helper_pfb_get_display_area(
            &ptDispAdapter->use_as__arm_2d_helper_pfb_t);
    
    /* initialise dirty region 0 at runtime
     * this demo shows that we create a region in the centre of a screen(320*240)
     * for a image stored in the tile c_tileCMSISLogoMask
     */
    arm_2d_align_centre(tScreen, c_tileCMSISLogoMask.tRegion.tSize) {
        s_tDirtyRegions[0].tRegion = __centre_region;
    }
    
    if (NULL == ptThis) {
        ptThis = (user_scene_3_t *)malloc(sizeof(user_scene_3_t));
        assert(NULL != ptThis);
        if (NULL == ptThis) {
            return NULL;
        }
    } else {
        bUserAllocated = true;
        memset(ptThis, 0, sizeof(user_scene_3_t));
    }
    
    *ptThis = (user_scene_3_t){
        .use_as__arm_2d_scene_t = {
        /* Please uncommon the callbacks if you need them
         */
        //.fnBackground   = &__pfb_draw_scene3_background_handler,
        .fnScene        = &__pfb_draw_scene3_handler,
        //.ptDirtyRegion  = (arm_2d_region_list_item_t *)s_tDirtyRegions,
        

        //.fnOnBGStart    = &__on_scene3_background_start,
        //.fnOnBGComplete = &__on_scene3_background_complete,
        //.fnOnFrameStart = &__on_scene3_frame_start,
        .fnOnFrameCPL   = &__on_scene3_frame_complete,
        .fnDepose       = &__on_scene3_depose,
        },
        .bUserAllocated = bUserAllocated,
    };

    arm_2d_scene_player_append_scenes(  ptDispAdapter, 
                                        &this.use_as__arm_2d_scene_t, 
                                        1);
    PAGE_CUR = 3;
    return ptThis;
}




#if defined(__clang__)
#   pragma clang diagnostic pop
#endif

#endif

